package face.jx.sdk;

import android.Manifest.permission;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PreviewCallback;
import android.os.Bundle;
import android.os.Process;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.RelativeLayout;
import android.widget.Toast;

import java.io.IOException;

import face.jx.sdk.util.PermissionResultCallBack;
import face.jx.sdk.util.PermissionUtil;

/**
 *
 */

public class BaseFaceActivity extends Activity {
        private final static String TAG = BaseFaceActivity.class.getSimpleName();
        protected SurfaceView mPreviewSurface;
        private SurfaceView mFaceSurface;
        protected Camera mCamera;

        protected int mCameraId = CameraInfo.CAMERA_FACING_FRONT;
        // Camera nv21格式预览帧的尺寸，默认设置640*480
        protected int PREVIEW_WIDTH = 640;
        protected int PREVIEW_HEIGHT = 480;
        // 预览帧数据存储数组和缓存数组
        protected byte[] nv21;
        protected byte[] buffer;
        // 缩放矩阵
        private Matrix mScaleMatrix = new Matrix();
        private boolean mStopTrack;
        private Toast mToast;
        private long mLastClickTime;
        private int isAlign = 0;
        private int mRequestCode = 1000;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_face);
            initUI();
            nv21 = new byte[PREVIEW_WIDTH * PREVIEW_HEIGHT * 2];
            buffer = new byte[PREVIEW_WIDTH * PREVIEW_HEIGHT * 2];
        }


        private Callback mPreviewCallback = new Callback() {

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                closeCamera();
            }

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                openCamera();
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                       int height) {
                mScaleMatrix.setScale(width/(float)PREVIEW_HEIGHT, height/(float)PREVIEW_WIDTH);
            }
        };

        private void setSurfaceSize() {
            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);

            int width = metrics.widthPixels;
            int height = (int) (width * PREVIEW_WIDTH / (float)PREVIEW_HEIGHT);
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)mPreviewSurface.getLayoutParams();
            RelativeLayout.LayoutParams layoutParamsFace = (RelativeLayout.LayoutParams)mPreviewSurface.getLayoutParams();
            layoutParams.width = width;
            layoutParams.height = height;
            layoutParamsFace.width = width;
            layoutParamsFace.height = height;
            mPreviewSurface.setLayoutParams(layoutParams);
            mFaceSurface.setLayoutParams(layoutParamsFace);
        }

        @SuppressLint("ShowToast")
        @SuppressWarnings("deprecation")
        private void initUI() {
            mPreviewSurface = (SurfaceView) findViewById(R.id.sfv_preview);
            mFaceSurface = (SurfaceView) findViewById(R.id.sfv_face);

            mPreviewSurface.getHolder().addCallback(mPreviewCallback);
            mPreviewSurface.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            mFaceSurface.setZOrderOnTop(true);
            mFaceSurface.getHolder().setFormat(PixelFormat.TRANSLUCENT);

            // 点击SurfaceView，切换摄相头
            mFaceSurface.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // 只有一个摄相头，不支持切换
                    if (Camera.getNumberOfCameras() == 1) {
                        showTip("只有后置摄像头，不能切换");
                        return;
                    }
                    closeCamera();
                    if (CameraInfo.CAMERA_FACING_FRONT == mCameraId) {
                        mCameraId = CameraInfo.CAMERA_FACING_BACK;
                    } else {
                        mCameraId = CameraInfo.CAMERA_FACING_FRONT;
                    }
                    openCamera();
                }
            });

            // 长按SurfaceView 500ms后松开，摄相头聚集
            mFaceSurface.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            mLastClickTime = System.currentTimeMillis();
                            break;
                        case MotionEvent.ACTION_UP:
                            if (System.currentTimeMillis() - mLastClickTime > 500) {
                                mCamera.autoFocus(null);
                                return true;
                            }
                            break;

                        default:
                            break;
                    }
                    return false;
                }
            });

            setSurfaceSize();
            mToast = Toast.makeText(BaseFaceActivity.this, "", Toast.LENGTH_SHORT);
        }

        protected void openCamera() {
            if (null != mCamera) {
                return;
            }

            if (!checkCameraPermission()) {
                showTip("摄像头权限未打开，请打开后再试");
                requestPermissions();
                mStopTrack = true;
                return;
            }

            // 只有一个摄相头，打开后置
            if (Camera.getNumberOfCameras() == 1) {
                mCameraId = CameraInfo.CAMERA_FACING_BACK;
            }

            try {
                mCamera = Camera.open(mCameraId);
                if (CameraInfo.CAMERA_FACING_FRONT == mCameraId) {
                    showTip("前置摄像头已开启，点击可切换");
                } else {
                    showTip("后置摄像头已开启，点击可切换");
                }
            } catch (Exception e) {
                e.printStackTrace();
                closeCamera();
                return;
            }

            Parameters params = mCamera.getParameters();
            params.setPreviewFormat(ImageFormat.NV21);
            params.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
            mCamera.setParameters(params);

            // 设置显示的偏转角度，大部分机器是顺时针90度，某些机器需要按情况设置
            mCamera.setDisplayOrientation(90);
            mCamera.setPreviewCallback(new PreviewCallback() {

                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    System.arraycopy(data, 0, nv21, 0, data.length);
                }
            });

            try {
                mCamera.setPreviewDisplay(mPreviewSurface.getHolder());
                mCamera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private void closeCamera() {
            if (null != mCamera) {
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
        }

        private boolean checkCameraPermission() {
            int status = checkPermission(permission.CAMERA, Process.myPid(), Process.myUid());
            return PackageManager.PERMISSION_GRANTED == status;

        }

        @Override
        protected void onResume() {
            super.onResume();

            mStopTrack = false;
            new Thread(new Runnable() {

                @Override
                public void run() {
                    while (!mStopTrack) {
                        if (null == nv21) {
                            continue;
                        }

                        synchronized (nv21) {
                            System.arraycopy(nv21, 0, buffer, 0, nv21.length);
                        }

                        // 获取手机朝向，返回值0,1,2,3分别表示0,90,180和270度
//                        int direction = Accelerometer.getDirection();
                        boolean frontCamera = (CameraInfo.CAMERA_FACING_FRONT == mCameraId);
                        // 前置摄像头预览显示的是镜像，需要将手机朝向换算成摄相头视角下的朝向。
                        // 转换公式：a' = (360 - a)%360，a为人眼视角下的朝向（单位：角度）
//                        if (frontCamera) {
//                            // SDK中使用0,1,2,3,4分别表示0,90,180,270和360度
//                            direction = (4 - direction)%4;
//                        }


                        Canvas canvas = mFaceSurface.getHolder().lockCanvas();
                        if (null == canvas) {
                            continue;
                        }

                        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                        canvas.setMatrix(mScaleMatrix);
//
//                        if( faces == null || faces.length <=0 ) {
//                            mFaceSurface.getHolder().unlockCanvasAndPost(canvas);
//                            continue;
//                        }
//
//                        if (null != faces && frontCamera == (CameraInfo.CAMERA_FACING_FRONT == mCameraId)) {
//                            for (FaceRect face: faces) {
//                                face.bound = PictureUtil.RotateDeg90(face.bound, PREVIEW_WIDTH, PREVIEW_HEIGHT);
//                                if (face.point != null) {
//                                    for (int i = 0; i < face.point.length; i++) {
//                                        face.point[i] = PictureUtil.RotateDeg90(face.point[i], PREVIEW_WIDTH, PREVIEW_HEIGHT);
//                                    }
//                                }
//                                PictureUtil.drawFaceRect(canvas, face, PREVIEW_WIDTH, PREVIEW_HEIGHT,
//                                        frontCamera, false);
//                            }
//                        } else {
//                            Log.d(TAG, "faces:0");
//                        }

                        mFaceSurface.getHolder().unlockCanvasAndPost(canvas);
                    }
                }
            }).start();
        }

        @Override
        protected void onPause() {
            super.onPause();
            closeCamera();
            mStopTrack = true;
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
        }

        private void showTip(final String str) {
            mToast.setText(str);
            mToast.show();
        }

        /**
         * 请求所需权限
         */
        private void requestPermissions(){
            PermissionUtil.getInstance().request(BaseFaceActivity.this, new String[]{permission.CAMERA,permission.WRITE_EXTERNAL_STORAGE}, mRequestCode,
                    new PermissionResultCallBack() {
                        @Override
                        public void onPermissionGranted() {
                            // 当全部权限的申请被用户允许之后,该方法会被调用
                            openCamera();
                        }

                        @Override
                        public void onPermissionDenied(String... permissions) {
                            // 当权限申请中的某一个或多个权限,被用户以前否定了,并确认了不再提醒时,也就是权限的申请窗体不能再弹出时,该方法将会被调用
                        }

                        @Override
                        public void onRationalShow(String... permissions) {
                            // 当权限申请中的某一个或多个权限,被用户否定了,但没有确认不再提醒时,也就是权限窗体申请时,但被否定了之后,该方法将会被调用.
                        }
                    });
        }

        // 申请权限返回结果
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            PermissionUtil.getInstance().onRequestPermissionResult(requestCode, permissions, grantResults);
        }
    }
